import axios, { AxiosResponse } from 'axios';
import { ElMessage, ElMessageBox } from 'element-plus';
import router from '@/router/index';
import auth from '@/common/auth';
interface ResType {
  records?: never[];
  code?: number;
  data?: any;
  msg?: string;
  total?: number;
  message?: string;
  err?: string;
  contentType?: string;
  fileName?: string;
}
interface Http {
  get(url: string, params?: unknown, headers?: any): Promise<ResType>;
  post(url: string, params?: unknown, headers?: any): Promise<ResType>;
  delete(url: string, params?: unknown, headers?: any): Promise<ResType>;
  put(url: string, params?: unknown, headers?: any): Promise<ResType>;
  upload(url: string, params?: unknown, headers?: any): Promise<ResType>;
}

// 设置请求头和请求路径
const productCode = import.meta.env.VITE_PRODUCT_CODE;
axios.defaults.baseURL = import.meta.env.VITE_BASE_URL;
axios.defaults.timeout = 60000;
axios.defaults.headers.post['Content-Type'] = 'application/json;charset=UTF-8';
axios.interceptors.request.use(
  (config) => {
    // 自定义headers
    const token = auth.getToken();
    if (config.headers) {
      if (token) {
        config.headers.token = token;
        config.headers['product-code'] = productCode;
      }

      // 设置responseType，用来下载Excel等文件
      const responseType = config.headers.responseType;
      if (responseType) {
        config.responseType = 'blob';
      }
    }
    return config;
  },
  (error) => {
    return error;
  },
);

//单独针对登录进行拦截，避免页面提示多次'请重新登录'；
let needLogin = false;
// 响应拦截
axios.interceptors.response.use(
  (res: AxiosResponse) => {
    // 下载文件，接口不返回code
    if (res.headers['content-disposition'] && res.headers['content-disposition'].indexOf('filename=') !== -1) {
      const downFile = {
        contentType: res.headers['content-type'],
        fileName: res.headers['content-disposition'].split('filename=')[1],
        data: res.data,
      };
      // 必须封装一层data，便于下一步解析
      return Promise.resolve({ data: downFile });
    }

    const code = res.data.code;

    // code === 0请求成功
    if (code === 0) {
      return Promise.resolve(res.data);
    } else {
      // 缺少token或者token失效，重新登录
      if ((code === 100 || code === -100) && !needLogin) {
        needLogin = true;
        auth.removeToken();
        ElMessageBox.confirm(res.data.msg, '提示', {
          type: 'warning',
          confirmButtonText: '确定',
          showCancelButton: false,
          showClose: false,
          closeOnClickModal: false,
        })
          .then(() => {
            router.replace('/login');
            // router.replace(`/login?redirect=${encodeURIComponent(router.currentRoute.value.fullPath)}`);
          })
          .catch(() => {})
          .finally(() => {
            needLogin = false;
          });
        return Promise.reject(res.data);
      }
      if (!needLogin) {
        // 导出文件失败，将blob转换json，并弹出错误提示
        if (res.data && res.config.responseType == 'blob') {
          const reader = new FileReader();
          reader.readAsText(res.data, 'utf-8');
          reader.onload = () => {
            // @ts-ignore
            const result = JSON.parse(reader.result || '');
            ElMessage.error(result.msg);
          };
          return Promise.reject({ msg: '文件导出失败' });
        }
        // res.data.message = response.data.msg;
        ElMessage.error(res.data.msg);
        return Promise.reject(res);
      }
    }
  },
  (error) => {
    const res = error.response;
    if (res.status == 404) {
      ElMessage.error('请求不存在，请稍后再试');
    }
    // const errorTxt = JSON.stringify(error);
    // if (errorTxt.includes('timeout')) {
    //   ElMessage.error('响应超时，请稍后再试');
    //   return Promise.reject(error.response);
    // }
    // ElMessage.error(error.message || error.msg || '请求出错，请稍后再试');
    else if (res.data) {
      ElMessage.error(res.data.msg || '请求出错，请稍后再试');
    } else {
      ElMessage.error('请求出错，请稍后再试');
    }
    return Promise.reject(error.response);
  },
);

const http: Http = {
  get(url, params, headers) {
    return new Promise((resolve, reject) => {
      axios({ method: 'get', url, params, headers })
        .then((res) => {
          resolve(res);
          // resolve(res.data);
        })
        .catch((err) => {
          reject(err.data);
        });
    });
  },
  post(url, params, headers) {
    return new Promise((resolve, reject) => {
      axios({ method: 'post', url, data: params, headers })
        .then((res) => {
          resolve(res);
          // resolve(res.data);
        })
        .catch((err) => {
          reject(err.data);
        });
    });
  },
  delete(url, params, headers) {
    return new Promise((resolve, reject) => {
      axios({ method: 'delete', url, params, headers })
        .then((res) => {
          resolve(res);
          // resolve(res.data);
        })
        .catch((err) => {
          reject(err.data);
        });
    });
  },
  put(url, params, headers) {
    return new Promise((resolve, reject) => {
      axios({ method: 'put', url, data: params, headers })
        .then((res) => {
          resolve(res);
          // resolve(res.data);
        })
        .catch((err) => {
          reject(err.data);
        });
    });
  },
  upload(url, file) {
    return new Promise((resolve, reject) => {
      axios
        .post(url, file, {
          headers: { 'Content-Type': 'multipart/form-data' },
        })
        .then((res) => {
          resolve(res);
          // resolve(res.data);
        })
        .catch((err) => {
          reject(err.data);
        });
    });
  },
};
export default http;
